     

    program main
      use globalvalues
      use precisions
      use routines_generic
      use types_generic
      use solveVSL
      use simulate
      
      implicit none

      ! Declarations
      type(typeGrids) :: grids
      type(typeValPol) :: valpol
      type(typeParams) :: params, origParams
      type(typeTech) :: tech, origTech
      type(typeSim) :: sim    
      type(typeProfiles) :: profiles
      type(typeProfilesAnn) :: profilesAnn,  profilesAnnTL(4)
      type(typeReadInParams) :: readParams(numParamsCombGlob)
      integer :: numRuns, ixR
    
    integer :: ixi, ixj, ixt
    integer :: numParams
    character(130) :: path_inMain, path_outMain, outfileMain
    

                      
          call readInParms(readParams, numParamsCombGlob, tech%allIn)

          ! Populate my types with globals so that globals do not play a role in the underlying code
          call populateTypes(grids, params, tech)

          ! An object for setting other parameters and technology that are not set in the globals file
          call getData(grids, params, tech)

        
          numRuns = numParamsCombGlob
          
   
                
 
      
          do ixR =1, numRuns, 1 

             ! Delete the results files
            call getpaths(path_inMain, path_outMain, ixR)                    
            outfileMain = trim(path_outMain) // 'results.out'               
            open (unit=250, file=outfileMain, recl=25000, action='write', status='replace')
            close(250)    
            
            


                  call resetTypes(ixR, numParamsCombGlob, readParams, params, tech, grids)
      

              do whichGuy = 1,numpeeps, 1  


                        

     

                        if (tech%unscaled) then
                            if (tech%addLoadOn) then 
                                tech%annRates = tech%annRatesAll(:,whichGuy,2, 2) 
                            else
                                tech%annRates = tech%annRatesAll(:,whichGuy, 1, 2) 
                            end if
                        else
                            if (tech%addLoadOn) then 
                                tech%annRates = tech%annRatesAll(:,whichGuy,2, 1) 
                            else
                                tech%annRates = tech%annRatesAll(:,whichGuy, 1, 1) 
                            end if
                        end if
                       tech%annRateSubjForPrinting = tech%annRatesSubj(:,whichGuy)

                
                        if (tech%obj) then                    
                            if (tech%unscaled) then
                                tech%surv  = tech%survProbAllObjUnscaled(:,whichGuy)    
                            else
                                tech%surv  = tech%survProbAllObj(:,whichGuy)  
                            end if                    
                        else                    
                            tech%surv = tech%survProbAll(:,whichGuy) 
                        end if

                        if (tech%housing) then
                             params%imputedRentForUtil = tech%allIn(whichGuy)%imputedRent  
                        else
                             params%imputedRentForUtil =  0.0_rk                 
                        end if
                
         
                        tech%SSlevel = tech%allIn(whichGuy)%statePen
                        startAGlob = tech%allIn(whichGuy)%Assets
                       
                        grids%assMax = startAGlob*1.05_rk ! don't change this - annuity grid depends on it                                
                        sim%startA = startAGlob                  
                        tech%ageAtSurvey = tech%allIn(whichGuy)%age                
                        tech%id = tech%allIn(whichGuy)%id                
                
                        call getgrids(tech, grids)
                
                      ! Call the solution
                      call vfi(grids, params, tech, valpol)
      
                      ! Simulate
                      call dosim(grids, params, tech, sim, valpol, profiles, ixR)             
                
         
                          profilesAnn%cons(:, whichGuy) =  profiles%cons(:,1)
                          profilesAnn%assStart(:, whichGuy) =  profiles%assStart(:,1)
                          profilesAnn%assEnd(:, whichGuy) =  profiles%assEnd(:,1)
                          profilesAnn%Y(:, whichGuy) =  profiles%Y(:,1)
                          profilesAnn%val(:, whichGuy) =  profiles%val(:,1)
                          profilesAnn%annProp(:, whichGuy) =  profiles%annProp(:,1)
                      


              end do
              
               ! Need to get some summary statistics here
               call sumstats(profilesAnn%cons, grids%maxT , numPeeps, profilesAnn%consMean, profilesAnn%consSD)
               call sumstats(profilesAnn%assStart, grids%maxT , numPeeps, profilesAnn%assStartMean, profilesAnn%assStartSD)
               call sumstats(profilesAnn%assEnd, grids%maxT , numPeeps, profilesAnn%assEndMean, profilesAnn%assEndSD)
               call sumstats(profilesAnn%Y, grids%maxT , numPeeps, profilesAnn%YMean, profilesAnn%YSD)
               call sumstats(profilesAnn%val, grids%maxT , numPeeps, profilesAnn%valMean, profilesAnn%valSD)
               call sumstats(profilesAnn%annProp, grids%maxT , numPeeps, profilesAnn%annPropMean, profilesAnn%annPropSD)              
              
              ! Print
              if (printingGlob.ne.0) call printsimdetail(profilesAnn, sim, ixR)   

      end do !ixR
      
 
        
    contains
    

    

    

       
    

       subroutine resetTypes(ixRunDum, numParamsCombDum, readParamsDum, paramsDum, techDum, gridsDum)
            implicit none
            integer, intent(in) :: ixRunDum, numParamsCombDum
            type(typeParams), intent(inout) :: paramsDum
            type(typeTech), intent(inout) :: techDum
            type(typeGrids), intent(inout) :: gridsDum
            type(typeReadInParams) :: readParamsDum(numParamsCombDum)
            
            integer :: ixnode_yest, ixnode_tod, ixyear
            real (kind=rk) :: sumforcdf
            
            paramsDum%gamma = readParamsDum(ixRunDum)%gamma
            paramsDum%OneMinusGamma = 1.0_rk-paramsDum%gamma
            paramsDum%beta =readParamsDum(ixRunDum)%beta       
            techDum%annOn = readParamsDum(ixRunDum)%annOn
            tech%housing =  readParamsDum(ixRunDum)%housing
            tech%addLoadOn = readParams(ixRunDum)%addMinLoad
            tech%obj =  readParams(ixRunDum)%obj
            tech%unscaled = readParams(ixRunDum)%unscaled    
            tech%discreteAnn =  readParams(ixRunDum)%discreteAnn  
            
            write(*,*)
            write(*,*) '********************************************************************'
            write(*,*)  ixRunDum                 
            write(*,*) 'gamma is', paramsDum%gamma
            write(*,*) 'beta is', paramsDum%beta
            write(*,*) 'annOn is', techDum%annOn 
            write(*,*) 'housing is',tech%housing 
            write(*,*) 'addLoad is', tech%addLoadOn 
            write(*,*) 'obj is', tech%obj 
            write(*,*) 'unscaled is', tech%unscaled                       
    
        end subroutine resetTypes
    
        subroutine populateTypes(grids, params, tech)
            implicit none
            type(typeGrids), intent(inout) :: grids
            type(typeParams), intent(inout) :: params
            type(typeTech), intent(inout) :: tech
            
           
            ! Params
            params%freeMinCons = freeMinConsGlob

            ! Technology
            tech%r = rGlob
            tech%annAdminLoad = annAdminLoadGlob
            tech%survProbOn = survProbOnGlob
            tech%retireAge = retireAgeGlob  
            tech%annOn= annOnGlob
      
            tech%maxT = yearsGlob
            tech%SSlevel = SSlevelGlob            

            
         ! Grids
            grids%maxA = assGlob
            
            grids%maxT = yearsGlob                    
            grids%cPoints = consGridGlob
            grids%annPoints = annPointsGlob
          
            grids%maxYY = incYGlob            
            grids%maxYO = incOGlob

            
            grids%assMin = assMinGlob
            grids%assMax = startAGlob*1.05_rk
            grids%retireAge = retireAgeGlob
         
            
            ! Simulation
            sim%numSims = numSimsGlob
            sim%startA = startAGlob
            
            
            if (grids%retireAge .ne. tech%retireAge) then
                write(*,*) 'Error in populateTypes'
                stop
            end if
            
         
        end subroutine populateTypes
      

        
    end program main
    